package com.ryder.subject.domain.service.impl;

import com.alibaba.fastjson2.JSON;
import com.ryder.subject.common.entity.PageResult;
import com.ryder.subject.common.enums.IsDeleteFlagEnum;
import com.ryder.subject.common.enums.SubjectCollectStatusEnum;
import com.ryder.subject.common.util.LoginUtil;
import com.ryder.subject.domain.convert.SubjectCollectBOConverter;
import com.ryder.subject.domain.entity.SubjectCollectBO;
import com.ryder.subject.domain.redis.RedisUtil;
import com.ryder.subject.domain.service.SubjectCollectDomainService;
import com.ryder.subject.infra.basic.entity.SubjectCollect;
import com.ryder.subject.infra.basic.entity.SubjectInfo;
import com.ryder.subject.infra.basic.service.SubjectCollectService;
import com.ryder.subject.infra.basic.service.impl.SubjectInfoServiceImpl;
import com.xxl.job.core.context.XxlJobHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 描述: 题目收藏表 领域service实现类
 *
 * @author ryder
 * @version 1.0
 * @since 1.0 // 版本号，指明从哪个版本开始
 * 更新日期: 2025-03-16 11:29:20
 */
@Service
@Slf4j
public class SubjectCollectDomainServiceImpl implements SubjectCollectDomainService {

    @Resource
    private SubjectCollectService subjectCollectService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private SubjectInfoServiceImpl subjectInfoService;

    private static final String SUBJECT_COLLECT_KEY = "subject.collect";

    private static final String SUBJECT_COLLECT_COUNT_KEY = "subject.collect.count";

    private static final String SUBJECT_COLLECT_DETAIL_KEY = "subject.collect.detail";

    @Override
    public void add(SubjectCollectBO subjectCollectBO) {
        Long subjectId = subjectCollectBO.getSubjectId();
        String likeUserId = subjectCollectBO.getLikeUserId();
        Integer status = subjectCollectBO.getStatus();
        String hashKey = buildSubjectCollectKey(String.valueOf(subjectId), likeUserId);
        redisUtil.putHash(SUBJECT_COLLECT_KEY, hashKey, status);
        String detailKey = SUBJECT_COLLECT_DETAIL_KEY + "." + subjectId + "." + likeUserId;
        String countKey = SUBJECT_COLLECT_COUNT_KEY + "." + subjectId;
        if (SubjectCollectStatusEnum.COLLECT.getCode() == status) {
            if (!redisUtil.hasHash(detailKey)) {
                redisUtil.increment(countKey, 1);
                redisUtil.set(detailKey, "1");
            }
        } else {
            Integer count = redisUtil.getInt(countKey);
            if (Objects.isNull(count) || count <= 0) {
                return;
            }
            redisUtil.increment(countKey, -1);
            redisUtil.del(detailKey);
        }
    }

    private String buildSubjectCollectKey(String subjectId, String likeUserId) {
        return subjectId + ":" + likeUserId;
    }

    @Override
    public Boolean update(SubjectCollectBO subjectCollectBO) {
        SubjectCollect subjectCollect = SubjectCollectBOConverter.INSTANCE.convertBOToEntity(subjectCollectBO);
        return subjectCollectService.update(subjectCollect) > 0;
    }

    @Override
    public Boolean delete(SubjectCollectBO subjectCollectBO) {
        SubjectCollect subjectCollect = new SubjectCollect();
        subjectCollect.setId(subjectCollectBO.getId());
        subjectCollect.setIsDeleted(IsDeleteFlagEnum.DELETED.getCode());
        return subjectCollectService.update(subjectCollect) > 0;
    }

    @Override
    public PageResult<SubjectCollectBO> getSubjectCollectPage(SubjectCollectBO subjectCollectBO) {
        PageResult<SubjectCollectBO> pageResult = new PageResult<>();
        pageResult.setPageNo(subjectCollectBO.getPageNo());
        pageResult.setPageSize(subjectCollectBO.getPageSize());
        int start = (subjectCollectBO.getPageNo() - 1) * subjectCollectBO.getPageSize();
        SubjectCollect subjectCollect = SubjectCollectBOConverter.INSTANCE.convertBOToEntity(subjectCollectBO);
        subjectCollect.setLikeUserId(LoginUtil.getLoginId());
        int count = subjectCollectService.countByCondition(subjectCollect);
        if (count == 0) {
            return pageResult;
        }
        List<SubjectCollect> subjectCollectList = subjectCollectService.queryPage(subjectCollect, start,
                subjectCollectBO.getPageSize());
        List<SubjectCollectBO> subjectCollectBOS = SubjectCollectBOConverter.INSTANCE.convertEntityToBoList(subjectCollectList);
        subjectCollectBOS.forEach(liked -> {
            SubjectInfo subjectInfo = subjectInfoService.queryById(liked.getSubjectId());
            liked.setSubjectName(subjectInfo.getSubjectName());
        });
        pageResult.setRecords(subjectCollectBOS);
        pageResult.setTotal(count);
        return pageResult;
    }

    @Override
    public void syncCollect() {
        Map<Object, Object> subjectCollectMap = redisUtil.getHashAndDelete(SUBJECT_COLLECT_KEY);
        if (log.isInfoEnabled()) {
            log.info("SubjectLikedDomainServiceImpl.syncCollect.subjectCollectMap:{}", JSON.toJSONString(subjectCollectMap));
        }
        if (MapUtils.isEmpty(subjectCollectMap)) {
            return;
        }
        //批量同步到数据库
        List<SubjectCollect> subjcetCollectList = new LinkedList<>();
        subjectCollectMap.forEach((k, v) -> {
            // 将拿到的每条 SubjectLiked 封装到 subjectLikedList
            SubjectCollect subjectCollect = new SubjectCollect();
            String s = k.toString();
            String[] keyArr = s.split(":");
            String subjectId = keyArr[0];
            String likedUser = keyArr[1];
            subjectCollect.setSubjectId(Long.valueOf(subjectId));
            subjectCollect.setLikeUserId(likedUser);
            subjectCollect.setStatus(Integer.valueOf(v.toString()));
            subjectCollect.setIsDeleted(IsDeleteFlagEnum.UN_DELETED.getCode());
            subjectCollect.setCreatedBy(String.valueOf(XxlJobHelper.getJobId()));
            subjectCollect.setCreatedTime(new Date());
            subjcetCollectList.add(subjectCollect);
        });
        //批量插入数据
        subjectCollectService.batchInsert(subjcetCollectList);
    }

}
